package com.example.demo.util;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.example.demo.config.CertConstants;
import com.example.demo.config.EncryptorsClassEnum;
import com.example.demo.encrypt.AESUtils;
import com.example.demo.encrypt.Encryptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;

/**
 * 验签解密获取加解密bean等
 *
 * @author yuancheng@belink.com
 * @date 2018/12/4
 */
public class VerifyAndDecryptUtil {

    private static final Logger logger = LoggerFactory.getLogger(VerifyAndDecryptUtil.class);

    private static Map<String, Encryptor> encryptorMap = new HashMap<>();

    /**
     * 从本地缓存中获取加解密的bean
     *
     * @param type 加解密类型
     */
    public static Encryptor getEncryptor(String type) throws Exception {
        String typeUpperCase = type.toUpperCase(Locale.getDefault());
        Encryptor encryptor = encryptorMap.get(typeUpperCase);
        if (null == encryptor) {
            Class<? extends Encryptor> clazz = EncryptorsClassEnum.valueOf(typeUpperCase).getClazz();
            encryptor = clazz.newInstance();
            encryptorMap.put(type, encryptor);
        }
        return encryptor;
    }

    /**
     * 对响应结果进行签名验证
     * @param encryptedResult 加密签名后的数据
     * @param publicKey 平台公钥
     * @return 根据响应结果解析的json对象
     */
    public static JSONObject verifySignature(String encryptedResult, String publicKey) throws Exception {
        Map<String, Object> map = JSONObject.parseObject(
                encryptedResult, new TypeReference<TreeMap<String, Object>>() {});
        Object obj = map.remove("signData");
        JSONObject json = new JSONObject(map);
        Encryptor encryptor = VerifyAndDecryptUtil.getEncryptor(json.getString("signType"));

        boolean bl = encryptor.verifySignature(json.toJSONString(), obj.toString(), publicKey);
        if (!bl) {
            logger.error("The result signature verify failed, encryptedResult is : {} ", encryptedResult);
            throw new IllegalArgumentException("Verify signature failed.");
        }
        return json;
    }

    /**
     * 解密AES密钥，然后用AES密钥对返回结果进行解密
     *
     * @param json 根据返回结果得到的json对象
     * @param privateKey 商户私钥
     * @return 解密后的http response
     */
    public static String decryptResult(JSONObject json, String privateKey) throws Exception {
        String encryptedRandomKey = json.getString("randomKeyEncrypt");
        String encryptType = json.getString("encryptType");
        Encryptor encryptor = VerifyAndDecryptUtil.getEncryptor(encryptType);
        String randomKey = encryptor.decrypt(encryptedRandomKey, privateKey);
        if(CertConstants.ENC_RSAV2.equalsIgnoreCase(encryptType)) {
            return AESUtils.decryptWithCBC(json.getString("data"), randomKey);
        }else{
            return AESUtils.decrypt(json.getString("data"), randomKey);
        }
    }
}
